
class SearchResult {
  constructor({ site_icon = '', site_name = '',
                title = '', image = '', link = '', description = '' } = {}) {
    this.site_icon = site_icon;
    this.site_name = site_name;
    this.title = title;
    this.image = image;
    this.link = link;
    this.description = description;
  }
}

class Episode {
  constructor({ title = '', link = '' } = {}) {
    this.title = title;
    this.link = link;
  }
}

class Source {
  constructor({ title = '', episodes = [] } = {}) {
    this.title = title;
    this.episodes = episodes;
  }
}

class WebsiteInfo {
  constructor({ type, title = '', link, sources = [],
                playUrl = null, sourceIndex = -1, episodeIndex = -1 } = {}) {
    this.type = type;
    this.title = title;
    this.link = link;
    this.sources = sources;
    this.playUrl = playUrl;
    this.sourceIndex = sourceIndex;
    this.episodeIndex = episodeIndex;
  }
}

class PlayUrlInfo {
  constructor({ type, urls, options = [], backupUrls = [] } = {}) {
    this.type = type;
    this.urls = urls;
    this.options = options;
    this.backupUrls = backupUrls;
  }
}

class AbstractPlugin {

  static DEFAULT_USER_AGENT = 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_13_0) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/64.0.3260.2 Safari/537.36';

  /**
   * 搜索视频, 返回 SearchResult[] 列表
   * @param {string} query - 搜索词
   * @returns {Promise<SearchResult[]>}
   */
  async fetchSearchResults(query) { throw new Error("Must implement fetchSearchResults."); }

  /**
   * 获取站点信息, 返回 WebsiteInfo
   * @returns {Promise<WebsiteInfo>}
   */
  async fetchWebsiteInfo() { throw new Error("Must implement fetchWebsiteInfo."); }

  /**
   * 获取播放链接, 返回 PlayUrlInfo
   * @returns {Promise<PlayUrlInfo>}
   */
  async fetchPlayUrlInfo(url) { throw new Error("Must implement fetchPlayUrlInfo."); }

  static findEpisode(sources, link) {
    for(let i = 0; i < sources.length; i++) {
      const source = sources[i];
      for(let j = 0; j < source.episodes.length; j++) {
        const episode = source.episodes[j];
        if(episode.link === link) {
          return [i, j];
        }
      }
    }
    return [-1, -1];
  }

}

function doHttpRequest(url, options, callback) {
  window.flutter_inappwebview.callHandler('httpRequestHandler', url, options).then((response) => {
    if(callback) callback(response);
  });
}

async function doHttpRequestSync(url, options) {
  return await window.flutter_inappwebview.callHandler('httpRequestHandler', url, options);
}

async function getAllPlugins(methodName) {
  const ALL_PLUGIN_CLASS_NAMES = await window.flutter_inappwebview.callHandler('getAllPluginClassHandler');
  const ALL_PLUGIN_CLASS = eval(ALL_PLUGIN_CLASS_NAMES);
  return ALL_PLUGIN_CLASS.filter(pluginClass => {
    return methodName === undefined || methodName === null || pluginClass.prototype.hasOwnProperty(methodName);
  }).map(pluginClass => new pluginClass());
}

async function getFirstPlugin(methodName) {
  const ALL_PLUGIN_CLASS_NAMES = await window.flutter_inappwebview.callHandler('getAllPluginClassHandler');
  const ALL_PLUGIN_CLASS = eval(ALL_PLUGIN_CLASS_NAMES);
  const pluginClass = ALL_PLUGIN_CLASS.find(pluginClass => {
    return methodName === undefined || methodName === null || pluginClass.prototype.hasOwnProperty(methodName);
  });
  return pluginClass ? new pluginClass() : null;
}

function doFetchSearchResults(query, callback) {
  getAllPlugins('fetchSearchResults').then((plugins) => {
    let fetchNum = plugins.length
    if(callback) callback(null, fetchNum)
    for(const plugin of plugins) {
      plugin.fetchSearchResults(query).then((result) => {
        fetchNum--;
        if(callback) callback(result, fetchNum);
      });
    }
  });
}

function doFetchWebsiteInfo() {
  getFirstPlugin('fetchWebsiteInfo').then((plugin) => {
    if(plugin) {
      plugin.fetchWebsiteInfo().then((result) => {
        window.flutter_inappwebview.callHandler('onWebsiteInfoHandler', result);
      });
    }
  });
}

function doFetchPlayUrlInfo(url) {
  getFirstPlugin('fetchPlayUrlInfo').then((plugin) => {
    if(plugin) {
      plugin.fetchPlayUrlInfo(url).then((result) => {
        window.flutter_inappwebview.callHandler('onPlayUrlInfoHandler', result);
      });
    }
  });
}
